/*
 * =====================================================================================
 *
 *       Filename:  ip-mac-conv.c
 *
 *    Description:  ip and mac convertion
 *
 *        Version:  1.0
 *        Created:  2020年02月25日 11时02分46秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Yuan Yulei (yyl), yyl_nudt@qq.com
 *   Organization:  National University Defense of Technology
 *
 * =====================================================================================
 */

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> 

/*
 * convert ip of no more than 16 byte string separated by char '.' to ip of 4 byte
 * input:
 *  char strIP[16]: ip of no more than 16 byte string separated by char '.'
 * output:
 *  uint8_t ip[4]: ip of 4 byte
 * return 0 if function success
 */
int 
str2ip(uint8_t ip[4], char strIP[16])
{
	char *ipstr = NULL;  
	char str_ip_index[4]={'\0'};  
	uint32_t ip_int, ip_add, ip_int_index[4], ip_temp_numbr;  
	ip_add = 0;
	ip_temp_numbr = 24;
	int i, j, a;
	j = 0;
	a = 0;		
	for(i =0; i<=16; i++)//要用到'\0'  
	{  
		if (strIP[i]=='\0' || strIP[i]=='.')  
		{             
			ip_int = atoi(str_ip_index);   
			if (ip_int<0||ip_int>255)  
			{  
				printf("IP地址有误\n");  
				system("pause");  
				return -1;       
			}  

			ip[a] = ip_int;
			a++;  
			memset(str_ip_index,0,sizeof(str_ip_index));  
			j=0;  
			continue;  
		}  

		str_ip_index[j] = strIP[i];  
		j++;  
	}     
	return 0;
}


/*
 * convert ip of 4 byte to string of no more than 16 byte, every field separated by char '.'
 * input:
 *  uint8_t ip[4]: ip of 4 byte
 * output:
 *  char str[16]: ip of no more than 16 byte, every field separated by char '.'
 * return 0 if function success
 */
int
ip2str(char str[16], uint8_t ip[4])
{
	sprintf(str, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); 
	//printf("str %s\n", str);
	return 0;
}
  
/*
 * convert ip of no more than 16 byte string separated by char '.' to ip of 4 byte 
 * input:
 *  char strIP[16]: ip of no more than 16 byte string separated by char '.'
 * output:
 *  uint8_t ip[4]: ip 
 */
int
ipstr2ip(uint8_t ip[4], char strIP[16])
{
	char str_ip_index[4]={'\0'};
	uint32_t ip_int,ip_add=0,ip_int_index[4],ip_temp_numbr=24;
	int j =0,a=0;	
	for(uint32_t i =0; i<=16; i++)//要用到'\0'
	{
		if (strIP[i]=='\0'||strIP[i]=='.')
		{			
			ip_int = atoi(str_ip_index);	
			if (ip_int<0||ip_int>255)
			{
				printf("IP地址有误\n");
				system("pause");
				return 1;				
			}
			ip[a] = ip_int; 
			if (strIP[i] == '\0')
				break;
			a++;
			memset(str_ip_index,0,sizeof(str_ip_index));
			j=0;
			continue;
		}
		str_ip_index[j] = strIP[i];
		j++;
	}	
	return 0;	
}
  
/*
 * convert ip of 4 byte to int
 * input:
 *  uint8_t pip[4]: ip of 4 byte
 * ourput:
 *  uint32_t* lip: return the int of ip
 */
int 
ip2int(uint32_t* lip, uint8_t pip[4])
{
	uint8_t *str = lip;
	str[0] = pip[3];
	str[1] = pip[2];
	str[2] = pip[1];
	str[3] = pip[0];
	return 0;	
}

/*
 * convert ip of no more than 16 byte string separated by char '.' to int
 * input:
 *  char strIP[16]: ip of no more than 16 byte string separated by char '.'
 * output:
 *  uint32_t* lip: int of ip
 */
int
ipstr2int(uint32_t* lip, const char strIP[16])
{
	uint8_t pip[4];
	ipstr2ip(pip, strIP);
	ip2int(lip, pip);
	return 0;	

#if 0
	char str_ip_index[4]={'\0'};
	uint32_t ip_int,ip_add=0,ip_int_index[4],ip_temp_numbr=24;
	int j =0,a=3;	
	for(uint32_t i =0; i<=16; i++)//要用到'\0'
	{
		if (strIP[i]=='\0'||strIP[i]=='.')
		{			
			ip_int =atoi(str_ip_index);	
			if (ip_int<0||ip_int>255)
			{
				printf("IP地址有误\n");
				system("pause");
				return 0;				
			}
 
			ip_add+=(ip_int*((uint32_t)pow(256.0,a)));			
			a--;
			memset(str_ip_index,0,sizeof(str_ip_index));
			if (strIP[i] == '\0')
				break;
			j=0;
			continue;
		}
 
		str_ip_index[j] = strIP[i];
		j++;
	}	
	*lip = ip_add;
	return 0;	
#endif
}
 
/*
 * convert ip of int to ip of 4 byte
 * input:
 *  uint32_t ip_int: ip of int
 * output:
 *  uint8_t ip[4]: ip of 4 byte
 */
int
int2ip(uint8_t ip[4], uint32_t ip_int)
{
#if 0
	ip[0] = ip_int >> 24;
	ip[1] = (ip_int<<8) >> 24;
	ip[2] = (ip_int<<16) >> 24;
	ip[3] = (ip_int<<24) >> 24;
#endif
	uint8_t *p = &ip_int;
	ip[0] = p[3];
	ip[1] = p[2];
	ip[2] = p[1];
	ip[3] = p[0];
	return 0;	
}

/*
 * convert ip of int to ip of no more than 16 byte string
 * input :
 *  uint32_t ip_int: ip of int
 * output:
 *  char ip_str[16]: ip of no more than 16 byte string
 */
int
int2ipstr(char ip_str[16], uint32_t ip_int)
{
	int j;
	uint32_t ip_int_index[4],ip_temp_numbr=24;
	//转换成x.x.x.x
	for(j=0;j<4;j++)
	{
		ip_int_index[j]=(ip_int>>ip_temp_numbr) & 0xFF;
		ip_temp_numbr-=8;
	}
 
	sprintf(ip_str, "%d.%d.%d.%d", ip_int_index[0], ip_int_index[1], ip_int_index[2], ip_int_index[3]);
	printf("%s\n",ip_str);
	return 0;
}

/*
 * 将6Byte的mac地址转换为':'隔开的字符串
 * input: 
 *       uint8_t pMac[6]: 6Byte表示的mac地址
 * output:
 *       char szMac[32]: 字符串表示的mac地址
 */
int 
mac2str(char szMac[32], uint8_t pMac[6], const char chKen/* = ':'*/)
{
	char szFormat[] = "%02X:%02X:%02X:%02X:%02X:%02X";
	int nLen = strlen(szFormat);
	if (chKen != ':')
	{
		for (int i = 2;i < nLen;i += 3)
		{
			szFormat[i] = chKen;
		}
	}
 
	//char szMac[32] = {0};
	sprintf(szMac, szFormat, pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5]);
	return 0;
}

/*
 * 将6Byte的mac地址转换为8Byte的整型数
 * input:
 *       uint8_t pMac[6]: 6Byte表示的mac地址
 * output:
 *       uint64_t lMac: mac地址的8Byte整型数,各字节左移实现
 */
int
mac2int(uint64_t* lMac, uint8_t pMac[6])
{
#if 1
	uint8_t *str = lMac;
	memset(str, 0, 8);
	str[0] = pMac[5];
	str[1] = pMac[4];
	str[2] = pMac[3];
	str[3] = pMac[2];
	str[4] = pMac[1];
	str[5] = pMac[0];
#endif
#if 0
	*lMac = 0;
	*lMac += (uint64_t)pMac[0] << 40;
	*lMac += (uint64_t)pMac[1] << 32;
	*lMac += (uint64_t)pMac[2] << 24;
	*lMac += (uint64_t)pMac[3] << 16;
	*lMac += (uint64_t)pMac[4] << 8;
	*lMac += (uint64_t)pMac[5];
#endif
	return 0;
}

/*
 * 将8Byte整型数表示的mac地址转换为6Byte数组表示的mac地址
 * input:
 *       uint64_t lMac: 8Byte整型数表示的mac地址
 * output:
 *       uint8_t pMac[6]: 6Byte数组表示的mac地址
 */
	int
int2mac(uint8_t pMac[6], uint64_t lMac)
{
#if 1
	pMac[0] = lMac >> 40;
	pMac[1] = (lMac & 0x00FF00000000) >> 32;
	pMac[2] = (lMac & 0x0000FF000000) >> 24;
	pMac[3] = (lMac & 0x000000FF0000) >> 16;
	pMac[4] = (lMac & 0x00000000FF00) >> 8;
	pMac[5] = (lMac & 0x0000000000FF);
#endif
#if 0
	uint8_t *p = &lMac;
	pMac[0] = p[5];	
	pMac[1] = p[4];	
	pMac[2] = p[3];	
	pMac[3] = p[2];	
	pMac[4] = p[1];	
	pMac[5] = p[0];	
#endif
	return 0;
}

uint8_t charToData(const char ch)
{
	switch(ch)
	{
	case '0': return 0;
	case '1': return 1;
	case '2': return 2;
	case '3': return 3;
	case '4': return 4;
	case '5': return 5;
	case '6': return 6;
	case '7': return 7;
	case '8': return 8;
	case '9': return 9;
	case 'a': 
	case 'A': return 10;
	case 'b': 
	case 'B': return 11;
	case 'c':
	case 'C': return 12;
	case 'd': 
	case 'D': return 13;
	case 'e': 
	case 'E': return 14;
	case 'f':
	case 'F': return 15;	
	}
	return 0;
}

/*
 * 将字符串表示的mac地址转换为6Byte
 * input: 
 *       const char *szMac: 字符串表示的mac地址
 * output:
 *       uint8_t pMac[6]: 6Byte表示的mac地址
 */
int 
str2mac(uint8_t pMac[6], const char * szMac)
{
	const char * pTemp = szMac;
	for (int i = 0;i < 6;++i)
	{
		pMac[i] = charToData(*pTemp++) * 16;
		pMac[i] += charToData(*pTemp++);
		pTemp++;
	}	
	return 0;
}

#if 0
int main()
{
	int i;
	//char str[] = "1A:2B:3C:4D:5E:6F";
	char str[] = "68:DB:54:C0:AA:8D";
	char str2[17];
	uint8_t mac[6];
	str2mac(mac, str);
	printf("\nstr is %s\nmac is:\n", str);
	for (i=0; i<6; i++)
		printf("%d\n", mac[i]);
	uint64_t lmac;
	mac2int(&lmac, mac);
	printf("\nint mac is %ld\n", lmac);
	lmac = 8490526488729266829;
	int2mac(mac, lmac);
	printf("\nlmac is %lu\nmac is:\n", lmac);
	for (i=0; i<6; i++)
		printf("%d\n", mac[i]);

	mac2str(str2, mac, ':');
	printf("str2 is %s\n", str2);


	char str3[] = "192.168.111.43";
	char str4[15];
	uint8_t ip[4];
	str2ip(ip, str3);
	printf("\nstr3 is %s\nip is:\n", str3);
	for (i=0; i<4; i++)
		printf("%d\n", ip[i]);

	ip2str(str4, ip);
	printf("str4 is %s\n", str4);
	return 0;
}
#endif

#if 0
int main()
{
	unsigned int ip_int;
	unsigned char ip[4];
	char ip_str[16] = "202.197.165.3";

	//ip_int = ipstr2int(ip_str);
	ipstr2int(&ip_int, ip_str);
	printf("ip_int %ld\n", ip_int);
	printf("ip_str %s\n", ip_str);

	int2ip(ip, ip_int);
	printf("ip %d %d %d %d\n", ip[0], ip[1], ip[2], ip[3]);

	ip2str(ip_str, ip);
	printf("ip_str %s\n", ip_str);

	ipstr2ip(ip, ip_str);
	printf("ip %d %d %d %d\n", ip[0], ip[1], ip[2], ip[3]);


	return 0;
}
#endif


